package com.maruti.otterapi.search;

import com.maruti.otterapi.ListParameters;
import com.maruti.otterapi.Otter4JavaException;
import com.maruti.otterapi.TopsyConfig;
import com.maruti.otterapi.TopsyConstants;
import com.maruti.otterapi.TopsyInvoker;

/**
 * @author Maruti Gollapudi (maruti (dot) gollapudi (at) gmail.com)
 * 
 *         Java wrapper for Otter API Version 0.1
 * 
 */
public class Search {

	private TopsyConfig topsyConfig;

	public TopsyConfig getTopsyConfig() {
		return topsyConfig;
	}

	public void setTopsyConfig(TopsyConfig topsyConfig) {
		this.topsyConfig = topsyConfig;
	}

	/**
	 * @param criteria
	 * @return
	 * @throws Otter4JavaException
	 */
	public SearchResponse search(SearchCriteria criteria) throws Otter4JavaException {
		if (criteria.getWindow() == null)
			criteria.setWindow("a");
		if (criteria.getListParams() == null || criteria.getListParams().getPage() == null)
			return fetchAll(criteria, "search");
		return fetch(criteria, "search");
	}

	public SearchResponse searchdate(SearchCriteria criteria) throws Otter4JavaException {
		if (criteria.getWindow() == null)
			criteria.setWindow("a");
		// if (criteria.getListParams() == null
		// || criteria.getListParams().getPage() == null)
		// return fetchAll(criteria, "searchdate");
		return fetch(criteria, "searchdate");
	}

	private SearchResponse fetchAll(SearchCriteria criteria, String type) throws Otter4JavaException {

		int page = 1;
		ListParameters listParameters = null;
		if (criteria.getListParams() != null)
			listParameters = criteria.getListParams();
		else
			listParameters = new ListParameters();
		listParameters.setPage("" + page);
		listParameters.setPerpage("100");
		criteria.setListParams(listParameters);
		SearchResponse response = fetch(criteria, type);
		int total = Integer.parseInt(response.getResult().getTotal());
		int fetchedRecs = response.getResult().getList().size();
		System.out.println(fetchedRecs);
		SearchResponse response1 = null;
		String lastOffset = response.getResult().getLast_offset();
		page++;
		while (total > fetchedRecs && page <= 10) {
			listParameters.setPage("" + page);
			// listParameters.setOffset(lastOffset);
			response1 = fetch(criteria, type);
			if (response1.getResult().getList().size() == 0) {
				System.out.println("No post crawled at this page. Skipping the rest of the pages...");
				break;
			}
			response.getResult().getList().addAll(response1.getResult().getList());
			fetchedRecs += response1.getResult().getList().size();
			System.out.println(response1.getResult().getList().size());
			lastOffset = response1.getResult().getLast_offset();
			page++;
		}

		return response;
	}

	private SearchResponse fetch(SearchCriteria criteria, String type) throws Otter4JavaException {
		TopsyInvoker invoker = new TopsyInvoker();
		invoker.setTopsyConfig(topsyConfig);

		String query = criteria.toQuery().replaceAll("\\s", "%20");
		String url = TopsyConstants.baseSearchURL;
		if ("searchdate".equalsIgnoreCase(type))
			url = TopsyConstants.baseSearchdateURL;

		SearchResponse data = (SearchResponse) invoker.fetchData(url + query, "search");
		aaa: while (data == null) {
			// try 3 times to ensure the current API key is dead
			System.out.println("No results crawled. We will try 3 times to ensure the key is expired.");
			for (int i = 1; i < 4; i++) {
				System.out.println("Attempt: " + i);
				data = (SearchResponse) invoker.fetchData(url + query, "search");
				if (data != null) {
					System.out.println("Successful! We will continue use the current key.");
					break aaa;
				}
			}
			
			System.out.println("Failed! We will try the next key if available.");
			// judge if there is another key available
			if (topsyConfig.getKeyOffset() < (topsyConfig.getApiKeys().length - 1)) {
				topsyConfig.setKeyOffset(topsyConfig.getKeyOffset() + 1);
				System.out.println("Changing to the next API Key: " + topsyConfig.getApiKeyCurrent());
				// re download the query using a new key
				data = (SearchResponse) invoker.fetchData(url + query, "search");
			} else {
				System.out.println("\n!!!No valid TOPSY API key! System will exit!!!\n");
				System.exit(1);
			}
		}

		return data;
	}

}
